package com.CMUBiS.PageControllers;

import java.util.ArrayList;

import javax.servlet.http.HttpServletRequest;

import com.CMUBiS.Data.Error;
import com.CMUBiS.Data.GlobalErrors;
import com.CMUBiS.Data.GlobalVars;
import com.CMUBiS.util.CheckInputs;
import com.CMUBiS.util.StopWatch;

/**
 * This is a blank example of a page controller. You can copy and edit it to make new pages
 * 
 * @author Andy (andrewtu@cmu.edu, turner.andy@gmail.com)
 * @version 0.1
 * @since 0.1
 * @date 04/05/2011
 */

public class BuyItemController extends PageController{
	// Variables passed in the request
	private int userID = -1;
	private String authToken = null;
	private int itemID;
	private int quantity;
	
	private int accountID = -1;
	private String creditCardNo;
	private String cvv;
	private Boolean cardIsValid;
	
	// Structures to hold the DB data
	
	// Structures to hold the parsed page data
	private String redirectURL = null;

	/**
	 * This method checks the page for any input errors that may have come from Client generator error
	 * These would need to be check in real life to stop users attempting to hack and mess with things
	 * 
	 * @param request
	 * @author Andy (andrewtu@cmu.edu, turner.andy@gmail.com)
	 */
	public void checkInputs(HttpServletRequest request){
		StopWatch timer;
		if(GlobalVars.collectStats){
			timer = new StopWatch();
			timer.start();
		}
		
		if(request != null){
			super.checkInputs(request);
			
			// Get the userID (if exists), we will pass it along to the next pages
			try{
				this.userID = CheckInputs.checkUserID(request);
			}
			catch(Error e){
				if(!errors.contains(e))
					errors.add(e);
			}
			
			// Get the authToken (if exists), we will pass it along to the next pages
			try{
				this.authToken = CheckInputs.checkAuthToken(request);
			}
			catch(Error e){
				if(!errors.contains(e))
					errors.add(e);
			}
			
			// Get the itemID 
			try{
				this.itemID = CheckInputs.checkItemID(request);
			}
			catch(Error e){
				if(!errors.contains(e))
					errors.add(e);
				
				this.itemID = -1;
			}
			
			// Get the quantity
			try{
				this.quantity = CheckInputs.checkQuantity(request);
			}
			catch(Error e){
				if(!errors.contains(e))
					errors.add(e);
				
				this.quantity = -1;
			}
			
			// Get the accountID
			try{
				this.accountID = CheckInputs.checkAccountID(request);
			}
			catch(Error e){
				// We don't care if the accountID is wrong as the user doesn't have to save the account
				this.accountID = -1;
			}
			
			// Get the credit card number
			this.creditCardNo = CheckInputs.getParameter(request, "creditCardNo");
			
			// Get the cvv code
			this.cvv = CheckInputs.getParameter(request, "cvv");
		}
		
		// Calculate how long that took
		if(GlobalVars.collectStats){
			timer.stop();
			this.totalGetParamTime += timer.getTimeTaken();
		}
	}

	/**
	 * This method get the data needed for the HTML4 page from the database
	 * 
	 * @author Andy (andrewtu@cmu.edu, turner.andy@gmail.com)
	 */
	public void getHTML4Data() {	
		StopWatch timer;
		if(GlobalVars.collectStats){
			timer = new StopWatch();
			timer.start();
		}
		
		// Calculate how long that took
		if(GlobalVars.collectStats){
			timer.stop();
			this.totalDBtime += timer.getTimeTaken();
		}
	}

	/**
	 * This method processes all of the data that was read from the database such that it is ready to be printed
	 * on to the page. We try to do as much of the page logic here as possible
	 * 
	 * @author Andy (andrewtu@cmu.edu, turner.andy@gmail.com)
	 */
	public void processHTML4() {
		StopWatch timer;
		if(GlobalVars.collectStats){
			timer = new StopWatch();
			timer.start();
		}
		
		// Calculate how long that took
		if(GlobalVars.collectStats){
			timer.stop();
			this.totalProcessingTime += timer.getTimeTaken();
		}
	}
	
	/**
	 * Gets the HTML5 data from the database
	 * 
	 * @author Andy (andrewtu@cmu.edu, turner.andy@gmail.com)
	 */
	public void getHTML5Data(){
		StopWatch timer;
		if(GlobalVars.collectStats){
			timer = new StopWatch();
			timer.start();
		}
		
		// Calculate how long that took
		if(GlobalVars.collectStats){
			timer.stop();
			this.totalDBtime += timer.getTimeTaken();
		}
	}
	
	/**
	 * Processes the HTML5 data that is needed to create the page
	 * 
	 * @author Andy (andrewtu@cmu.edu, turner.andy@gmail.com)
	 */
	public void processHTML5(){
		StopWatch timer;
		if(GlobalVars.collectStats){
			timer = new StopWatch();
			timer.start();
		}
		
		// Calculate how long that took
		if(GlobalVars.collectStats){
			timer.stop();
			this.totalProcessingTime += timer.getTimeTaken();
		}
	}
	
	private boolean verifyCardNumber(){
		// WOO!! it just wouldn't be made by students if we didn't copy from wikipedia!!
		// TODO: Andy: Check this algorithm is correct with a real book
		// ref: http://en.wikipedia.org/wiki/Luhn_algorithm
		
		final int[][] sumTable = {{0,1,2,3,4,5,6,7,8,9},{0,2,4,6,8,1,3,5,7,9}};
		
	    int sum = 0, flip = 0;
	 
	    try{
		    for (int i = this.creditCardNo.length() - 1; i >= 0; i--) {
		      sum += sumTable[flip++ & 0x1][Character.digit(this.creditCardNo.charAt(i), 10)];
		    }
		    
		    if(!(sum % 10 == 0))
		    	if(!errors.contains(GlobalErrors.creditCardNoInvalid))
		    		errors.add(GlobalErrors.creditCardNoInvalid);
	    }
	    catch(Exception e){
	    	if(!errors.contains(GlobalErrors.creditCardNoInvalid))
				errors.add(GlobalErrors.creditCardNoInvalid);
	    }
	    
		return false;
	}
	
	public boolean buyNow(){
		if(this.errors.size() == 0)
			if(GlobalVars.db.checkAuthToken(this.userID, this.authToken)){
				// Attempt to buy the item
				//Account account = new Account(this.accountID)
				
				//TODO: write the buy to the DB in the buyitemnow method
				boolean retVal2 = GlobalVars.db.buyItemNow(this.userID, this.itemID, this.quantity, this.accountID);
					
				if(retVal2) this.createRedirectURL();
					
				return retVal2;
			}
			else if(!errors.contains(GlobalErrors.incorrectAuthToken))
					errors.add(GlobalErrors.incorrectAuthToken);
		
		return false;
	}
	
	/**
	 * If we successfully buy the item then we'll need to forward them on to the next page.
	 * We'll create the URL here
	 * 
	 * @author Andy (andrewtu@cmu.edu, turner.andy@gmail.com)
	 */
	private void createRedirectURL(){
		this.redirectURL = "./myaccount?userID=" + this.userID + "&authToken=" + this.authToken;
	}
	
	/**
	 * Returns the current userID as a String
	 * 
	 * @return String the userID
	 * @author Andy (andrewtu@cmu.edu, turner.andy@gmail.com)
	 */
	public String getUserIDString(){
		return Integer.toString(this.userID);
	}
	
	/**
	 * Returns the authToken sent to the page
	 * 
	 * @return string the authToken
	 * @author Andy (andrewtu@cmu.edu, turner.andy@gmail.com)
	 */
	public String getAuthTokenString(){
		return this.authToken;
	}
}
